﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.Specialized;

namespace CrayonsBox
{
    /// <summary>
    /// Interaction logic for SpriteEditor.xaml
    /// </summary>
    public partial class SpriteEditor : UserControl
    {

        public SpriteEditor()
        {
            InitializeComponent();
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            DataModel.Sprite new_sprite = new DataModel.Sprite(dbxAnim.Document);
            
            this.lsImages.ItemsSource = DataModel.Sprite.ActiveItem.Images;
            this.gridModules.ItemsSource = DataModel.Sprite.ActiveItem.Modules;
            this.gridFrames.ItemsSource = DataModel.Sprite.ActiveItem.Frames;
            this.gridAnims.ItemsSource = DataModel.Sprite.ActiveItem.Animations;

            gridModules.SelectionChanged += gridModules_SelectionChanged;
            gridFrames.SelectionChanged += gridFrames_SelectionChanged;
            moduleDbox.MouseDown += moduleDbox_MouseDown;
            moduleDbox.MouseMove += moduleDbox_MouseMove;
            moduleDbox.MouseUp += moduleDbox_MouseUp;

            if (moduleDbox.Document.Layers["modules"] == null)
                moduleDbox.Document.Layers.Add(new Drawing.Document.Layer("modules"));

            if (moduleDbox.Document.Layers["images"] == null)
                moduleDbox.Document.Layers.Add(new Drawing.Document.Layer("images"));

            if (dbxFrame.Document.Layers["frames"] == null)
                dbxFrame.Document.Layers.Add(new Drawing.Document.Layer("frames"));

            if (dbxFrame.Document.Layers["inFrameModules"] == null)
                dbxFrame.Document.Layers.Add(new Drawing.Document.Layer("inFrameModules"));           

            lsImages.SelectionChanged += lsImages_SelectionChanged;
            
            DataModel.Sprite.ActiveItem.Modules.CollectionChanged += modules_CollectionChanged;
            DataModel.Sprite.ActiveItem.Images.CollectionChanged += images_CollectionChanged;
            DataModel.Sprite.ActiveItem.Frames.CollectionChanged += frames_CollectionChanged;
            DataModel.Sprite.ActiveItem.Animations.CollectionChanged += animations_CollectionChanged;

            dbxFrame.MouseDown += dbxFrame_MouseDown;
            dbxFrame.MouseMove += dbxFrame_MouseMove;
            dbxFrame.MouseUp += dbxFrame_MouseUp;
            dbxFrame.Document.SelectedItems.CollectionChanged += dbxFrame_SelectedItems_CollectionChanged;
            gridInFrameModules.SelectionChanged += gridInFrameModules_SelectionChanged;

            gridAnims.SelectionChanged += gridAnims_SelectionChanged;
            gridInAnimFrames.SelectionChanged += gridInAnimFrames_SelectionChanged;


            new_sprite.LoadJSON("..\\..\\..\\Samples\\buster.json"); // TEST ONLY
        }

        private void spriteTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            MahApps.Metro.Controls.MetroTabItem tab = spriteTabControl.SelectedItem as MahApps.Metro.Controls.MetroTabItem;

            if (tab.Header.Equals("Frames"))
                MainWindow.Instance.lsFrameModule.ItemsSource = DataModel.Sprite.ActiveItem.Modules;

            if (tab.Header.Equals("Animations"))
                MainWindow.Instance.lsFrameModule.ItemsSource = DataModel.Sprite.ActiveItem.Frames;
        }


        #region ## Modules Tab ##

        private void gridModules_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null)
            {
                moduleDbox.Document.Layers["modules"].IsVisible = true;
                foreach (DataModel.Sprite.Module mod in e.AddedItems)
                {
                    mod.IsVisible = true;
                    moduleDbox.Document.SelectedItems.Add(mod);
                    lsImages.SelectedIndex = mod.Image;
                }
            }

            if (e.RemovedItems != null)
            {
                foreach (DataModel.Sprite.Module mod in e.RemovedItems)
                {
                    mod.IsVisible = false;
                    moduleDbox.Document.SelectedItems.Remove(mod);
                }
            }          
        }

        private void lsImages_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null)
            {
                moduleDbox.Document.Layers["images"].IsVisible = true;                
                foreach(DataModel.Sprite.Image img in e.AddedItems)
                    img.IsVisible = true;
            }

            if (e.RemovedItems != null)
            {
                foreach (DataModel.Sprite.Image img in e.RemovedItems)
                    img.IsVisible = false;
            }
        }

        private void modules_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach(DataModel.Sprite.Module mod in e.NewItems)
                {
                    moduleDbox.Document.Layers["modules"].Drawables.Add(mod);
                    gridModules.SelectedItem = mod;
                }              
            }
        }

        private void images_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                int count = DataModel.Sprite.ActiveItem.Images.Count;
                string path = DataModel.Sprite.ActiveItem.Images[count - 1].Path;
                DataModel.Sprite.ActiveItem.Images[count - 1].ID = count - 1;
                DataModel.Sprite.ActiveItem.Images[count - 1].Picture = new System.Drawing.Bitmap(path);

                moduleDbox.Document.Layers["images"].Drawables.Add(DataModel.Sprite.ActiveItem.Images[count - 1]);

                lsImages.SelectedItem = DataModel.Sprite.ActiveItem.Images[count - 1];
            }
        }

        private void moduleDbox_MouseDown(object sender, MouseButtonEventArgs e)
        {
            
        }

        private void moduleDbox_MouseMove(object sender, MouseEventArgs e)
        {
            
        }

        private void moduleDbox_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
            {
                if (gridModules.SelectedItems != null)
                {
                    foreach (DataModel.Sprite.Module mod in gridModules.SelectedItems)
                    {
                        DataModel.Sprite.ActiveItem.CacheModule(mod.ID);
                    }
                }
            }
        }

        private void HandleButtonClick(object sender, RoutedEventArgs e)
        {
            if (sender.Equals(btnImageImport))
            {
                Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
                ofd.Multiselect = true;
                ofd.Filter = "JPEG Files (*.jpeg)|*.jpeg|" +
                            "PNG Files (*.png)|*.png|" +
                            "JPG Files (*.jpg)|*.jpg|" +
                            "All Files (*.*) |*.*";
                ofd.ShowDialog();

                for (int i = 0; i < ofd.FileNames.Length; i++)
                {
                    DataModel.Sprite.ActiveItem.Images.Add(new DataModel.Sprite.Image { Path = ofd.FileNames[i] });
                }
            }
            else if (sender.Equals(btnNewModule))
            {
                if (lsImages.SelectedItem == null)
                {
                    //Show dialog box to choose image first
                    return;
                }

                int count = DataModel.Sprite.ActiveItem.Modules.Count;
                DataModel.Sprite.ActiveItem.AddModule(new DataModel.Sprite.Module { ID = count, Image = lsImages.SelectedIndex });
            }
        }

        #endregion


        #region ## Frames Tab ##
        
        private void btnNewFrame_Click(object sender, RoutedEventArgs e)
        {
            int count = DataModel.Sprite.ActiveItem.Frames.Count;
            DataModel.Sprite.Frame newFrame = new DataModel.Sprite.Frame() { ID = count };
            DataModel.Sprite.ActiveItem.AddFrame(newFrame);
        }

        private void inFrameModules_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (DataModel.Sprite.InFrameModule ifm in e.NewItems)
                {
                    ifm.IsVisible = true;
                    dbxFrame.Document.Layers["inFrameModules"].Drawables.Add(ifm);
                }
                DataModel.Sprite.Frame fr = gridFrames.SelectedItem as DataModel.Sprite.Frame;
                DataModel.Sprite.ActiveItem.CacheFrame(fr.ID);
            }
        }

        private void gridFrames_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null)
            {
                dbxFrame.Document.Layers["frames"].IsVisible = true;
                foreach (DataModel.Sprite.Frame fr in e.AddedItems)
                {
                    fr.IsVisible = true;
                    gridInFrameModules.ItemsSource = fr.InFrameModules;
                    foreach(DataModel.Sprite.InFrameModule ifm in fr.InFrameModules)
                        ifm.IsVisible = true;
                    gridInFrameModules.SelectedIndex = 0;
                }
            }

            if (e.RemovedItems != null)
            {
                foreach (DataModel.Sprite.Frame fr in e.RemovedItems)
                {
                    fr.IsVisible = false;
                    foreach (DataModel.Sprite.InFrameModule ifm in fr.InFrameModules)
                    {
                        ifm.IsSelected = false;
                        ifm.IsVisible = false;
                    }
                }
            }
        }

        private void gridInFrameModules_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null)
            {
                dbxFrame.Document.Layers["inFrameModules"].IsVisible = true;
                foreach (DataModel.Sprite.InFrameModule ifm in e.AddedItems)
                {
                    if (!dbxFrame.Document.SelectedItems.Contains(ifm))
                    {
                        dbxFrame.Document.SelectedItems.Add(ifm);
                        ifm.IsVisible = true;
                    }
                }
            }

            if (e.RemovedItems != null)
            {
                foreach (DataModel.Sprite.InFrameModule ifm in e.RemovedItems)
                {
                    if (dbxFrame.Document.SelectedItems.Contains(ifm))
                    {
                        dbxFrame.Document.SelectedItems.Remove((ifm as Drawing.Document.Drawable));
                    }
                }
            }
        }

        private void frames_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (DataModel.Sprite.Frame fr in e.NewItems)
                {
                    dbxFrame.Document.Layers["frames"].Drawables.Add(fr);
                    fr.InFrameModules.CollectionChanged += inFrameModules_CollectionChanged;
                    gridFrames.SelectedItem = fr;
                }
            }
        }

        private void dbxFrame_SelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (Drawing.Document.Drawable dr in e.OldItems)
                {
                    DataModel.Sprite.InFrameModule ifm = dr as DataModel.Sprite.InFrameModule;
                    if (ifm != null)
                    {
                        gridInFrameModules.SelectedItems.Remove(ifm);
                    }
                }
            }
            else if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (Drawing.Document.Drawable dr in e.NewItems)
                {
                    DataModel.Sprite.InFrameModule ifm = dr as DataModel.Sprite.InFrameModule;
                    if (ifm != null)
                    {
                        gridInFrameModules.SelectedItems.Add(ifm);
                    }
                }
            }
            else if (e.Action == NotifyCollectionChangedAction.Reset)
            {
                gridInFrameModules.SelectedItems.Clear();
            }
        }

        public void btnInFrameModule_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            DataModel.Sprite.Module mod = (sender as Button).Tag as DataModel.Sprite.Module;
            
            if (gridFrames.SelectedItem == null) 
                return;

            DataModel.Sprite.Frame fr = gridFrames.SelectedItem as DataModel.Sprite.Frame;
            DataModel.Sprite.InFrameModule ifm = new DataModel.Sprite.InFrameModule(DataModel.Sprite.ActiveItem);
            ifm.ModuleID = mod.ID;
            fr.InFrameModules.Add(ifm);
        }


        private void dbxFrame_MouseDown(object sender, MouseButtonEventArgs e)
        {
        }

        private void dbxFrame_MouseMove(object sender, MouseEventArgs e)
        {
        }

        private void dbxFrame_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (gridFrames.SelectedItem != null)
            {
                DataModel.Sprite.Frame fr = gridFrames.SelectedItem as DataModel.Sprite.Frame;
                if (fr.IsDirty)
                    DataModel.Sprite.ActiveItem.CacheFrame(fr.ID);
            }
        }

        private void btnShowModuleList_Click(object sender, RoutedEventArgs e)
        {
            MainWindow.Instance.ToggleFlyout(0);
        }
        #endregion


        #region ## Animations Tab ##
        
        private void btnShowFramList_Click(object sender, RoutedEventArgs e)
        {
            MainWindow.Instance.ToggleFlyout(0);
        }

        private void animations_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                int count = DataModel.Sprite.ActiveItem.Animations.Count;
                DataModel.Sprite.Animation anim = DataModel.Sprite.ActiveItem.Animations[count - 1];
                anim.InAnimationFrames.CollectionChanged += inAnimationFrames_CollectionChanged;
                gridAnims.SelectedItem = anim;
            }
        }

        private void inAnimationFrames_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            //DataModel.Sprite.Animation anim = gridAnims.SelectedItem as DataModel.Sprite.Animation;

            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (DataModel.Sprite.Animation.InAnimationFrame iaf in e.NewItems)
                {
                    int nrLayer = dbxAnim.Document.OldLayers.Count;
                    iaf.LayerID = nrLayer;
                    dbxAnim.Document.OldLayers.AddLayer(DataModel.Sprite.ActiveItem.Frames[iaf.FrameID].Cache);
                }
            }
        }

        private void gridAnims_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null)
            {
                DataModel.Sprite.Animation anim = gridAnims.SelectedItem as DataModel.Sprite.Animation;
                gridInAnimFrames.ItemsSource = anim.InAnimationFrames;
                DataModel.Sprite.ActiveItem.IsVisible = true;
                DataModel.Sprite.ActiveItem.CurrentAnimation = anim.ID;
            }

            if (e.RemovedItems != null)
            {
                for (int i = 0; i < e.RemovedItems.Count; i++)
                {
                    DataModel.Sprite.Animation anim = e.RemovedItems[i] as DataModel.Sprite.Animation;
                    foreach(DataModel.Sprite.Animation.InAnimationFrame iaf in anim.InAnimationFrames)
                    {
                        dbxAnim.Document.OldLayers[iaf.LayerID].IsVisible = false;
                    }
                }
            }
        }

        private void gridInAnimFrames_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems != null)
            {
                for (int i = 0; i < e.AddedItems.Count; i++)
                {
                    DataModel.Sprite.Animation.InAnimationFrame iaf = e.AddedItems[i] as DataModel.Sprite.Animation.InAnimationFrame;
                    dbxAnim.Document.OldLayers[iaf.LayerID].IsVisible = true;
                }
            }

            if (e.RemovedItems != null)
            {
                for (int i = 0; i < e.RemovedItems.Count; i++)
                {
                    DataModel.Sprite.Animation.InAnimationFrame iaf = e.RemovedItems[i] as DataModel.Sprite.Animation.InAnimationFrame;
                    dbxAnim.Document.OldLayers[iaf.LayerID].IsVisible = false;
                }
            }
        }

        #endregion

    }
}
